/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
// -*- coding:iso-8859-15 mode: c++ -*-
/** 
 * \file
 * \brief MaCI_Wireless Player for logged files.
 * \author Matthieu Myrsky <matthieu.myrsky@tkk.fi>
 *
 * $Id: WirelessFilePlayer.cpp,v 1.5 2009-06-30 13:28:59 morsko Exp $
 *
 */

#include "WirelessFilePlayer.hpp"

WirelessFilePlayer::WirelessFilePlayer( MaCI::Wireless::CWirelessServer *aWirelessServer,
                                        std::string aFileName)
  :PlayerModule(),
   iWirelessServer(aWirelessServer),
   iData(),
   iTimes(),
   iBegin(),
   iEnd(),
   iFile(NULL),
   iName(""),
   iMeasurementIndexLogged(false)
{
 
  
  dPrint(3,"Opening file '%s'",aFileName.c_str());
  iFile= fopen(aFileName.c_str(),"rt");

  char c[200];
  char interfaceName[64];
  //Read the four first lines..and get the interfacename...
  fgets (c, 200,iFile );

  fscanf(iFile,"%s %s %s %s",c,c,c,interfaceName);
  fgets (c, 200,iFile );
  
  fgets (c, 200,iFile );
  std::string types(c);
  std::string::size_type loc = types.find( "measurementIndex", 0 );
  //dPrint(1,"%s",types.c_str());
  if( loc != std::string::npos ) {
    //dPrint(1,"measurementIndex Logged...");
    iMeasurementIndexLogged=  true;

  }

  iWirelessServer->SetInterfaceInstanceName(std::string(interfaceName));
  iWirelessServer->Open();

  iName = "MaCI_Wireless."+std::string(interfaceName);

  ReadData();
}
//*****************************************************************************

WirelessFilePlayer::~WirelessFilePlayer()
{
  fclose(iFile);
  delete(iWirelessServer);
}
//*****************************************************************************

bool WirelessFilePlayer::ReadData()
{
  using namespace MaCI::Wireless;
  MaCI::Common::TTimestamp timestamp;
  uint64_t nodeIDSignal, nodeIDRange, nodeIDPosition, nodeIDESSID;;
  uint32_t measurementIndex;
  float range, rangeVar,posX,posY,posZ;
  char ESSID[32];
  int signalLevel,signalCount, rangeCount, positionCount, ESSIDCount;

  bool first = true;
  int number = 1;
  while(number != 0 && number != EOF){

    CWirelessData *wData = new CWirelessData();
    wData->CreateInternalBinBag();
   

    //Check for the measurementIndex.. if any.
    if(iMeasurementIndexLogged){
      measurementIndex = fscanf(iFile,"%u",&measurementIndex);
      
      if(measurementIndex != 0){
        wData->SetMeasurementIndex(TMeasurementIndex(measurementIndex));
        
      }
    }

    //Check for timestamp and signalcount
    number = fscanf(iFile,"%u %u %d",
                    &(timestamp.timestamp_s),
                    &(timestamp.timestamp_us),
                    &signalCount);

    if(number >0){
      wData->SetTimestamp(timestamp);
    }else{
      break;
    }
   
    

    
    //Save the first timestamp
    if(first&& number == 3){
      iBegin = timestamp.GetGimTime();
      first = false;
    }

    //Get all signal levels and save them to wireless data
    for(int i =  0; i< signalCount; i++){

      number = fscanf(iFile,"%llx %d",
                      &nodeIDSignal, &signalLevel);

      if(number > 0){
        wData->AddNodeSignal(TNodeSignal(nodeIDSignal, signalLevel));
      }else{
        break;
      }
    }

    //Get range count
    number = fscanf(iFile,"%d",
                    &rangeCount);

    //Get all ranges and save them to wireless data
    for(int i =  0; i< rangeCount; i++){
      number = fscanf(iFile,"%llx %f %f",
                      &nodeIDRange,&range, &rangeVar);
      if(number > 0){
        wData->AddNodeRange(TNodeRange(nodeIDRange, range, rangeVar));
        
      }else{
        break;
      }     

      
    }
    //Get position count
    number = fscanf(iFile,"%d",
                &positionCount);

    //Get all positions and save them to wireless data
    for(int i =  0; i< positionCount; i++){
      number = fscanf(iFile,"%llx %f %f %f",
                      &nodeIDPosition,&posX,&posY,&posZ);
      if(number > 0){
        wData->AddNodePosition(TNodePosition(nodeIDPosition, posX,posY,posZ));
      }else{
        break;
      }     
        
    }

    //Get id count
    number = fscanf(iFile,"%d",
                    &ESSIDCount);

    //Get all ids and save them to wireless data
    for(int i =  0; i< ESSIDCount; i++){
      number = fscanf(iFile,"%llx '",
                      &nodeIDESSID);

      char c;
      int index = 0;
      while(1){
        c = fgetc(iFile);
        if(c == '\'' || index == 31) break;
        ESSID[index] = c;
        ++index;
      }
      ESSID[index] = '\0';
     
      if(number > 0){
        wData->AddNodeID(TNodeID(nodeIDESSID,ESSID));
      }else{
        break;
      }     
        
    }

    //Finally add wirelss data to map and timestamp to list
    if(wData){
      iData[timestamp.GetGimTime()] = wData;
      iTimes.push_back(timestamp.GetGimTime());
    }

    

  }
  if(!first){
    iEnd = timestamp.GetGimTime();
  }

  if(number == EOF){
    return true;
  }else{
    return false;
  }

}
//*****************************************************************************

bool WirelessFilePlayer::OnTime(gim::time aTime)
{
  std::map<gim::time,MaCI::Wireless::CWirelessData *>::iterator iter
    =iData.find(aTime);
  
  if(iter != iData.end()){
    iWirelessServer->SendWirelessEvent(*(iter->second));
    return true;
  }else{
    
    return false;
  }
  
}
//*****************************************************************************

bool WirelessFilePlayer::GetTimes(std::list<gim::time> *aTimes)
{
  
  aTimes->assign(iTimes.begin(),iTimes.end());
  return true;
}

//*****************************************************************************

std::string WirelessFilePlayer::GetName(void)
{
  return iName;

}
//*****************************************************************************

void WirelessFilePlayer::GetTimeLimits(gim::time &aBegin,gim::time &aEnd)
{
  aBegin = iBegin;
  aEnd = iEnd;
  dPrint(15,"begin %s, end %s",aBegin.toString().c_str(),aEnd.toString().c_str());
}
//*****************************************************************************







